//
// Created by Administrator on 2025-07-24.
//

#include "MySQLHandler.h"

MySQLHandler::MySQLHandler(const std::string &host, const std::string &user, const std::string &password,
             const std::string &database)
        : _host(host), _user(user), _password(password), _database(database), _bConnected(false), _pstMql(nullptr)
{
    connect();
}



MySQLHandler::~MySQLHandler()
{
    if (_pstMql)
    {
        mysql_close(_pstMql);
    }
}

MysqlData MySQLHandler::queryRecord(const std::string &sSql)
{
    MysqlData data;
    if (!_bConnected)
    {
        connect();
    }
    _sLastSql = sSql;
    int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
    if (iRet != 0)
    {
        int iErrno = mysql_errno(_pstMql);
        if (iErrno == 2013 || iErrno == 2006)
        {
            connect();
            iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
        }
    }
    if (iRet != 0)
    {
        throw TC_Mysql_Exception(
                "[TC_Mysql::execute]: mysql_query: [ " + sSql + " ] :" + std::string(mysql_error(_pstMql)));
    }
    MYSQL_RES *pstRes = mysql_store_result(_pstMql);
    if (pstRes == NULL)
    {
        throw TC_Mysql_Exception(
                "[TC_Mysql::queryRecord]: mysql_store_result: " + sSql + " : " + std::string(mysql_error(_pstMql)));
    }
    std::vector<std::string> vtFields;
    MYSQL_FIELD *field;
    while((field = mysql_fetch_field(pstRes)))
    {
        vtFields.push_back(field->name);
    }
    std::map<std::string, std::string> mpRow;
    MYSQL_ROW stRow;
    while((stRow = mysql_fetch_row(pstRes)) != (MYSQL_ROW) NULL)
    {
        mpRow.clear();
        unsigned long *lengths = mysql_fetch_lengths(pstRes);
        for(size_t i = 0; i < vtFields.size(); i++)
        {
            if (stRow[i])
            {
                mpRow[vtFields[i]] = std::string(stRow[i], lengths[i]);
            }
            else
            {
                mpRow[vtFields[i]] = "";
            }
        }
        data.data().push_back(mpRow);
    }
    mysql_free_result(pstRes);
    return data;
}

void MySQLHandler::insertRecord(const std::string &tableName, const std::map<std::string, std::string> &values)
{
    if (!_bConnected)
    {
        connect();
    }
    std::string columns;
    std::string valuesStr;
    bool first = true;
    for (const auto &pair : values)
    {
        if (!first)
        {
            columns += ", ";
            valuesStr += ", ";
        }
        columns += pair.first;
        valuesStr += "'" + pair.second + "'";
        first = false;
    }
    std::string sSql = "INSERT INTO " + tableName + " (" + columns + ") VALUES (" + valuesStr + ")";
    _sLastSql = sSql;
    int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
    if (iRet != 0)
    {
        int iErrno = mysql_errno(_pstMql);
        if (iErrno == 2013 || iErrno == 2006)
        {
            connect();
            iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
        }
    }
    if (iRet != 0)
    {
        throw TC_Mysql_Exception(
                "[TC_Mysql::insertRecord]: mysql_query: [ " + sSql + " ] :" + std::string(mysql_error(_pstMql)));
    }
}

void MySQLHandler::updateRecord(const std::string &tableName, const std::map<std::string, std::string> &setValues, const std::string &whereClause)
{
    if (!_bConnected)
    {
        connect();
    }
    std::string setStr;
    bool first = true;
    for (const auto &pair : setValues)
    {
        if (!first)
        {
            setStr += ", ";
        }
        setStr += pair.first + " = '" + pair.second + "'";
        first = false;
    }
    std::string sSql = "UPDATE " + tableName + " SET " + setStr + " WHERE " + whereClause;
    _sLastSql = sSql;
    int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
    if (iRet != 0)
    {
        int iErrno = mysql_errno(_pstMql);
        if (iErrno == 2013 || iErrno == 2006)
        {
            connect();
            iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
        }
    }
    if (iRet != 0)
    {
        throw TC_Mysql_Exception(
                "[TC_Mysql::updateRecord]: mysql_query: [ " + sSql + " ] :" + std::string(mysql_error(_pstMql)));
    }
}

void MySQLHandler::deleteRecord(const std::string &tableName, const std::string &whereClause)
{
    if (!_bConnected)
    {
        connect();
    }
    std::string sSql = "DELETE FROM " + tableName + " WHERE " + whereClause;
    _sLastSql = sSql;
    int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
    if (iRet != 0)
    {
        int iErrno = mysql_errno(_pstMql);
        if (iErrno == 2013 || iErrno == 2006)
        {
            connect();
            iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
        }
    }
    if (iRet != 0)
    {
        throw TC_Mysql_Exception(
                "[TC_Mysql::deleteRecord]: mysql_query: [ " + sSql + " ] :" + std::string(mysql_error(_pstMql)));
    }
}
